/**
 *		Licensed to the Apache Software Foundation (ASF) under one
 *     or more contributor license agreements.  See the NOTICE file
 *     distributed with this work for additional information
 *     regarding copyright ownership.  The ASF licenses this file
 *     to you under the Apache License, Version 2.0 (the
 *     "License"); you may not use this file except in compliance
 *     with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *      Unless required by applicable law or agreed to in writing,
 *     software distributed under the License is distributed on an
 *     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *     KIND, either express or implied.  See the License for the
 *     specific language governing permissions and limitations
 *     under the License.
 *     
 *     Image Resizer Project
 */
package image.resizer;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Start point for running resize process. 
 * @author DUDAREV
 */
public class ResizeEngine implements IResizeEngine{

	private static final String CLASS_NAME = ResizeEngine.class.getName();
	private static final Logger logger = Logger.getLogger(ResizeEngine.class.getPackage().getName());
	private static final Level FINER_LEVEL = Level.FINER;
	
	private static final String IMAGE_JPG = "jpeg"; //TODO move to file manager ?
	
	private ResizerConfig configuration;
	private FileManager fileManager;
	private ProgressEventsManager progressManager;
	
	public ResizeEngine() {
		fileManager = new FileManager();
		progressManager = new ProgressEventsManager();
	}
	
	public void configureEngine(ResizerConfig config) {
		configuration = (ResizerConfig)config.clone();
		fileManager.setSearchSubDirs(config.isSearchSubDirs());
	}

	// TH
	/**
	 * Start running resize images task for current configuration.
	 */
	public void startResizing() {
		if(logger.isLoggable(FINER_LEVEL))
		{
			logger.entering(CLASS_NAME, "startResizing");
		}
		// TODO get files, loop resizer
		if(configuration == null)
		{
			RuntimeException rte = new RuntimeException("No configuration supplied for resize engine!");
			logger.throwing(CLASS_NAME, "startResizing", rte);
			throw rte;
		}
		String path = configuration.getSourceDirPath();
		// validating sourse directory
		File sourceDir = new File(path);
		if(!sourceDir.exists())
		{
			RuntimeException rte = new RuntimeException("Source directory not found for : "+sourceDir);
			logger.throwing(CLASS_NAME, "startResizing", rte);
			throw rte;
		}
		else
		{
			if(!sourceDir.isDirectory())
			{
				RuntimeException rte = new RuntimeException("Source directory is file. ("+sourceDir+")");
				logger.throwing(CLASS_NAME, "startResizing", rte);
				throw rte;
			}
		}
		String outPath = configuration.getTargetDirPath();
		// Validating target directory
		File targetDir = new File(outPath);
		if(targetDir.exists() && !targetDir.isDirectory())
		{
			RuntimeException rte = new RuntimeException("Target directory is file. ("+targetDir+")");
			logger.throwing(CLASS_NAME, "startResizing", rte);
			throw rte;
		}
		
		int numOfThreads = configuration.getNumOfThreads();
		// Validating num of threads
		if(numOfThreads < 1)
		{
			RuntimeException rte = new RuntimeException("Illegal number of threads: "+numOfThreads);
			logger.throwing(CLASS_NAME, "startResizing", rte);
			throw rte;
		}
		ImageResizer resizer = new ImageResizer();
		int maxImageSize = configuration.getMaxImageSize();
		if(maxImageSize < 1)
		{
			RuntimeException rte = new RuntimeException("Illegal image size: "+maxImageSize);
			logger.throwing(CLASS_NAME, "startResizing", rte);
			throw rte;
		}
		else
		{
			fileManager.initImageFileTree(path, outPath);
				for(int i = 0 ; i < numOfThreads ; i++)
				{
					RunnableResizer rResizer = new RunnableResizer(resizer, fileManager, maxImageSize);
					rResizer.setProgressListener(progressManager);
					Thread thread = new Thread(rResizer);
					thread.start();
				}
		}
		if(!targetDir.exists())
		{
			targetDir.mkdirs();
		}
		if(logger.isLoggable(FINER_LEVEL))
		{
			logger.exiting(CLASS_NAME, "startResizing");
		}
	}
	
	public static void resizeImage(ImageResizer resizer, ImageDescriptor imageDescriptor, int maxSize)
	{
		if(logger.isLoggable(FINER_LEVEL))
		{
			Object[] params = {"resizer: ", resizer, " imageDescriptor: ", imageDescriptor, " maxSize: ", maxSize};
			logger.entering(CLASS_NAME, "resizeImage", params);
		}
		BufferedImage bi = FileManager.readImage(imageDescriptor.getSourceFile());
		BufferedImage result = resizer.resizeIfBigger(bi, maxSize);
		FileManager.writeImage(result, imageDescriptor.getTargetPath(), IMAGE_JPG/*TODO move to fileManager ?*/);
		imageDescriptor.clear();
		if(logger.isLoggable(FINER_LEVEL))
		{
			logger.exiting(CLASS_NAME, "resizeImage");
		}
	}
	
	/**
	 * Answers progress information handler object.
	 */
	public IProgressInfo getProgressInfo() {
		if(logger.isLoggable(FINER_LEVEL))
		{
			logger.entering(CLASS_NAME, "getProgressInfo");
			logger.exiting(CLASS_NAME, "getProgressInfo", fileManager);
		}
		return fileManager;
	}
	
	/**
	 * Appending listener to receive work completion events.
	 */
	public void appendProgressListener(IProgressListener listener) {
		if(logger.isLoggable(FINER_LEVEL))
		{
			logger.entering(CLASS_NAME, "appendProgressListener", listener);
		}
		progressManager.appendListener(listener);
		if(logger.isLoggable(FINER_LEVEL))
		{
			logger.exiting(CLASS_NAME, "appendProgressListener");
		}
	}
}